#include "Input.h"


Input::Input(void) 
{
	m_pDIObject = 0;
	m_pDIKeyboard = 0;
	mouseClicked = false;
}

Input::~Input(void)
{
	release();
}

// Get instance of DInput
Input* Input::getInstance()
{
	static Input instance;
	return &instance;
}

// Create DInput, Keyboard & Mouse Objects
void Input::initialize(HWND hWnd, HINSTANCE hInst)
{
	m_hWnd = hWnd;	// Window handle

	// DInput Object
	DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&m_pDIObject, NULL);

	// Create Keyboard & Mouse Objects
	m_pDIObject->CreateDevice(GUID_SysKeyboard, &m_pDIKeyboard, NULL); 
	m_pDIObject->CreateDevice(GUID_SysMouse, &m_pDIMouse, NULL);

	// Set Keyboard & Mouse Data Formats
	m_pDIKeyboard->SetDataFormat(&c_dfDIKeyboard); 
	m_pDIMouse->SetDataFormat(&c_dfDIMouse2);

	// Set Coperation Levels
	m_pDIKeyboard->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); 
	m_pDIMouse->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); 

	// Acquire
	m_pDIKeyboard->Acquire();
	m_pDIMouse->Acquire();
}

// Poll Keyboard & Mouse for Input
void Input::pollDevices()
{
	// Temp structures
	// Keyboard
	for(int i=0; i<KEYBUF; ++i)
		keyboardState[i] = 0;
	// Mouse
	mouseState.lX = 0;	// pos x
	mouseState.lY = 0;	// pos y
	mouseState.lZ = 0;	// pos z
	mouseState.rgbButtons[0] = 0;	// left click
	mouseState.rgbButtons[1] = 0;	// right click
	mouseState.rgbButtons[2] = 0;	// scroll click

	// Poll Keyboard
	HRESULT hr = m_pDIKeyboard->GetDeviceState(sizeof(keyboardState), (void**)keyboardState);

	// refresh pressed keys
	for(int i=0; i<KEYBUF; ++i)
	{
		if( (! (keyboardState[i] & 0x80)) && keysLastUpdate[i] )
			keysLastUpdate[i] = false;
	}

	// check if call was successful
	if( FAILED(hr) )
	{
		// zero out keyboard data structure
		ZeroMemory(keyboardState, sizeof(keyboardState));
		// re-acquire
		m_pDIKeyboard->Acquire();
	}


	// Poll Mouse
	hr = m_pDIMouse->GetDeviceState(sizeof(mouseState), (void**)&mouseState);

	// check if call was successful
	if( FAILED(hr) )
	{
		// zero mouse data structure
		ZeroMemory(&mouseState, sizeof(mouseState));
		// re-acquire
		m_pDIMouse->Acquire();
	}

}

// check for key down
int Input::keyDown(int key)
{
	return (keyboardState[key] & 0x80);
}

// check for key press
bool Input::keyPressed(int key)
{
	if( keyboardState[key] & 0x80 && !keysLastUpdate[key] )
	{
		keysLastUpdate[key] = true;
		return true;
	}
	return false;
}

int Input::mouseButtonDown(int button)
{
	return (mouseState.rgbButtons[button] & 0x80);
}

V2DF Input::getMousePos()
{
	POINT cursorPos;
	V2DF pos = V2DF(0.0f,0.0f);

	GetCursorPos(&cursorPos);
	ScreenToClient(m_hWnd, &cursorPos);

	pos.x = cursorPos.x;
	pos.y = cursorPos.y;

	return pos;
}

void Input::release()
{
	// Keyboard & Mouse
	// safe release all created direct input objects
	m_pDIKeyboard->Unacquire();
	m_pDIMouse->Unacquire();
	if(!m_pDIKeyboard)
		m_pDIKeyboard->Release();
	if(!m_pDIMouse)
		m_pDIMouse->Release();
	if(!m_pDIObject)
		m_pDIObject->Release();
}